package com.ybear.mvp.event;

import android.app.Activity;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.IdentityHashMap;
import java.util.Map;

public final class MvpEventObserver {
    @Retention(RetentionPolicy.SOURCE)
    public @interface EventType {
        int ON_TOUCH = 0;
        int DISPATCH_TOUCH = 1;
        int DISPATCH_KEY = 2;
        int DISPATCH_KEY_SHORTCUT = 3;
        int DISPATCH_TRACKBALL = 4;
        int DISPATCH_GENERIC_MOTION = 5;
    }

    private final Map<Integer, OnEventCallback> mListener = new IdentityHashMap<>();
    private MvpEventObserver() {}
    public static MvpEventObserver get() { return HANDLER.I; }
    private static final class HANDLER {
        private static final MvpEventObserver I = new MvpEventObserver();
    }

    public <T extends InputEvent>void onDispatch(@Nullable Activity activity,
                                                 @EventType int type,
                                                 @NonNull T ev) {
        if( activity == null ) return;
        int findKey = getKey( activity );
        for( Integer key : mListener.keySet() ) {
            if( key.equals( findKey ) ) {
                OnEventCallback val = mListener.get( key );
                if( val == null ) return;
                switch ( type ) {
                    case EventType.ON_TOUCH:
                        if( ev instanceof MotionEvent ) {
                            val.onTouchEvent( (MotionEvent) ev );
                        }
                        break;
                    case EventType.DISPATCH_TOUCH:
                        if( ev instanceof MotionEvent ) {
                            val.dispatchTouchEvent( (MotionEvent) ev );
                        }
                        break;
                    case EventType.DISPATCH_KEY:
                        if( ev instanceof KeyEvent ) {
                            val.dispatchKeyEvent( (KeyEvent) ev );
                        }
                        break;
                    case EventType.DISPATCH_KEY_SHORTCUT:
                        if( ev instanceof KeyEvent ) {
                            val.dispatchKeyShortcutEvent( (KeyEvent) ev );
                        }
                        break;
                    case EventType.DISPATCH_TRACKBALL:
                        if( ev instanceof MotionEvent ) {
                            val.dispatchTrackballEvent( (MotionEvent) ev );
                        }
                        break;
                    case EventType.DISPATCH_GENERIC_MOTION:
                        if( ev instanceof MotionEvent ) {
                            val.dispatchGenericMotionEvent( (MotionEvent) ev );
                        }
                        break;
                }
            }
        }
    }

    public OnEventCallback registerEvent(@Nullable Activity activity, @NonNull OnEventCallback l) {
        if( activity == null ) return null;
        return mListener.put( getKey( activity ), l );
    }

    public OnEventCallback unRegisterEvent(@Nullable Activity activity) {
        if( activity == null ) return null;
        return mListener.remove( getKey( activity ) );
    }

    public OnEventCallback unRegisterEvent(@Nullable OnEventCallback l) {
        if( l == null ) return null;
        for( Integer key : mListener.keySet() ) {
            OnEventCallback val = mListener.get( key );
            if( val != null && val.equals( l ) ) {
                return mListener.remove( key );
            }
        }
        return null;
    }

    private int getKey(@NonNull Activity activity) {
        return activity.getClass().getName().hashCode();
    }
}
